﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TableParsers
{
    public class ClassNameException : Exception
    {
        String RawClassName = null;
        public ClassNameException(string originalValue)
        {
            RawClassName = originalValue;
        }
    }

    static class ClassNameParser
    {
        private static Dictionary<String, ClassKind> KindDictionary;
        private static Dictionary<String, ClassType> WorkshopDictionary;

        static ClassNameParser()
        {
            KindDictionary = new Dictionary<string, ClassKind>();
            KindDictionary.Add("WS", ClassKind.Workshop);
            KindDictionary.Add("CC", ClassKind.Group);
            KindDictionary.Add("SP", ClassKind.Club);
            KindDictionary.Add("CA", ClassKind.Club);
            KindDictionary.Add("BW", ClassKind.Bussiness);
            
            KindDictionary.Add("FC", ClassKind.Management);
            KindDictionary.Add("PF", ClassKind.Management);

            WorkshopDictionary = new Dictionary<string, ClassType>();
            WorkshopDictionary.Add("GRAMMAR", ClassType.Grammar);
            WorkshopDictionary.Add("WRITING", ClassType.Writing);
            WorkshopDictionary.Add("READING", ClassType.Reading);
            WorkshopDictionary.Add("CONVERSATION", ClassType.Conversation);
        }

        public static string ToCamelCase(string str)
        {
            string[] tokens = str.Split(' ');

            if (tokens.Length == 0) return str;

            for (int i = 0; i < tokens.Length; i++)
            {
                StringBuilder builder = new StringBuilder(tokens[i].ToLower());

                if (builder.Length > 0)
                {
                    builder[0] = Char.ToUpper(builder[0]);
                }

                tokens[i] = builder.ToString();
            }

            string result = tokens[0];
            for (int i = 1; i < tokens.Length; i++)
            {
                result += " " + tokens[i];
            }
            return result;
        }

        private static ClassName ParseGroupKindClass(string rawValue, string[] tokens)
        {
            /*Example: CC - GC 6 - RED */
            if (tokens.Length != 3)
            {
                throw new ClassNameException(rawValue);
            }

            string week = tokens[1];
            string color = tokens[2];
            week = week.Trim();
            color = color.Trim();

            string[] weekParts = week.Split(' ');
            if (weekParts.Length != 2)
            {
                throw new ClassNameException(rawValue);
            }

            string weekNumber = weekParts[1];

            return new ClassName(rawValue,
                                 ToCamelCase(color),
                                 ClassType.Group);
        }

        private static ClassName ParseClubKindClass(string rawValue, string[] tokens)
        {
            /*Example: CA - SPORT CLUB */
            if (tokens.Length != 2)
            {
                throw new ClassNameException(rawValue);
            }

            string name = tokens[1];
            name = name.Trim();

            /* remove 'club' word */
            string[] nameParts = name.Split(' ');
            string finalName = null;

            foreach (string val in nameParts)
            {
                if (!val.ToLower().Equals("club"))
                {
                    if (finalName == null)
                    {
                        finalName = val;
                    }
                    else
                    {
                        finalName += " " + val;
                    }
                }
            }

            return new ClassName(rawValue, ToCamelCase(finalName), ClassType.Club);
        }

        private static ClassName ParseBusinessKindClass(string rawValue, string[] tokens)
        {
            return new ClassName(rawValue, ToCamelCase("Business"), ClassType.Business);
        }

        private static ClassName ParseWorkshopKindClass(string rawValue, string[] tokens)
        {
            if (tokens.Length != 2)
            {
                throw new ClassNameException(rawValue);
            }

            /*Example: WS - WRITING WORKSHOP */
            string workshop = tokens[1];
            workshop = workshop.Trim();

            string[] workshopParts = workshop.Split(' ');

            if (workshopParts.Length < 2)
            {
                throw new ClassNameException(rawValue);
            }

            string name = workshopParts[0];
            name = name.Trim();

            ClassType type = WorkshopDictionary[name];
            return new ClassName(rawValue, ToCamelCase(name), type);
        }

        static ClassName ParseManagementKindClass(string rawValue, string[] tokens)
        {
            string id = tokens[0];
            if (id == "PF")
            {
                return new ClassName(rawValue, ToCamelCase("Progress Follow-up"), ClassType.ProgressFollowup);
            }
            else if (id == "FC")
            {
                return new ClassName(rawValue, ToCamelCase("First Class"), ClassType.FirstClass);
            }
            else
            {
                return new ClassName(rawValue, ToCamelCase("Unknown"), ClassType.Unknown);
            }
        }

        public static ClassName ParseClassName(String rawValue)
        {
            string[] tokens = rawValue.Split('-');

            if (tokens.Length == 0)
            {
                throw new ClassNameException(rawValue);
            }

            tokens[0] = tokens[0].Trim();
            string id = tokens[0];

            if (KindDictionary.Keys.Contains(id) == false)
            {
                return new ClassName(rawValue, rawValue, ClassType.Unknown);
            }

            ClassKind kind = KindDictionary[id];

            switch (kind)
            {
                case ClassKind.Group:
                    {
                        return ParseGroupKindClass(rawValue, tokens);
                    }
                case ClassKind.Club:
                    {
                        return ParseClubKindClass(rawValue, tokens);
                    }
                case ClassKind.Bussiness:
                    {
                        return ParseBusinessKindClass(rawValue, tokens);
                    }
                case ClassKind.Workshop:
                    {
                        return ParseWorkshopKindClass(rawValue, tokens);
                    }
                case ClassKind.Management:
                    {
                        return ParseManagementKindClass(rawValue, tokens);
                    }
            }

            return null;
        }
    }
}
